package cn.xxm.ff.log.core.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang.StringUtils;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * Created by xuxiaoming005 on 2018-08-13.
 */
public class DesentizationPolicyImpl implements DesensitizationPolicy {

    @Override
    public Object[] desensitizeArgs(Object[] objs, Map<String, Set<String>> map, boolean stringKillSwitch) {
        Map<String, List<String>> mapList = new HashMap<>(0);
        for (String k: map.keySet()) {
            mapList.put(k, map.get(k).stream().collect(Collectors.toList()));
        }


        return warpMessageArgs(objs, mapList, stringKillSwitch);
    }

    @Override
    public String desensitizeFormattedMessage(String formattedMessage, Map<String, Set<String>> map) {
        Map<String, List<String>> mapList = new HashMap<>(0);
        for (String k: map.keySet()) {
            mapList.put(k, map.get(k).stream().collect(Collectors.toList()));
        }

        int beginIndex = formattedMessage.indexOf("{");
        int endIndex = formattedMessage.lastIndexOf("}");

        String substring = preHandleJsonString(formattedMessage, beginIndex, endIndex);

        JSONObject json = JSONObject.parseObject(handleStringBeforeParse(substring));

        // 脱敏
        this.cardNoDesensitization(json, mapList.get("cardNames"));
        this.custNameDesensitization(json, mapList.get("custKeyNames"));
        this.emailDesensitization(json, mapList.get("emailKeyNames"));
        this.hemoAddressDesensitization(json,
                mapList.get("homeAddressKeys"));
        this.idNoDesensitization(json, mapList.get("idNoKeyNames"));
        this.mobileNoDesensitization(json, mapList.get("phoneKeyNames"));
        this.otherDesensitization(json, mapList.get("otherKeyNames"));
        formattedMessage = new StringBuilder(formattedMessage)
                .replace(beginIndex, endIndex + 1,
                        json.toJSONString()).toString();

        return formattedMessage;
    }

    /**
     * 预处理json字符串信息
     * @param formattedMessage 格式化的消息
     * @param beginIndex json字符串开始位置
     * @param endIndex json字符串结束位置
     * @return 处理过循环引用的json字符串
     */
    private String preHandleJsonString(String formattedMessage, int beginIndex, int endIndex) {
        String substring = formattedMessage.substring(beginIndex, endIndex + 1);
        if (StringUtils.contains(substring, "\\\"")) {
            substring = StringUtils.replace(substring, "\\\"", "\"");
        }

        substring = handleStringBeforeParse(substring);
        return substring;
    }

    /**
     * 对日志参数脱敏
     *
     * @param args
     * @return
     */

    private Object[] warpMessageArgs(Object[] args, Map<String, List<String>> map, boolean stringKillSwitch) {

        Object[] result = new Object[args.length];
        for (int i = 0; i < args.length; i++) {
            Object o = args[i];
            JSONObject json = null;
            // 对string做json转换
            try {
                if (o instanceof String) {
                    json = JSONObject.parseObject(handleStringBeforeParse((String) o));
                } else if (o instanceof JSONObject) {
                    json = JSONObject.parseObject(handleStringBeforeParse(JSONObject.toJSONString(o)));
                } else if (o instanceof Map) {
                    String jsonStr = JSONObject.toJSONString(o);
                    json = JSONObject.parseObject(jsonStr);
                } else {
                    String jsonStr = JSONObject.toJSONString(o);
                    json = JSONObject.parseObject(jsonStr);
                }
            } catch (Exception e) {
                if (stringKillSwitch) {
                    result[i] = "************";
                } else {
                    result[i] = o;
                }
                continue;
            }
            if (json != null) {// 脱敏
                // 卡号脱敏
                this.cardNoDesensitization(json, map.get("cardNames"));
                this.custNameDesensitization(json, map.get("custKeyNames"));
                this.emailDesensitization(json, map.get("emailKeyNames"));
                this.hemoAddressDesensitization(json,
                        map.get("homeAddressKeys"));
                this.idNoDesensitization(json, map.get("idNoKeyNames"));
                this.mobileNoDesensitization(json, map.get("phoneKeyNames"));
                this.otherDesensitization(json, map.get("otherKeyNames"));

            }
            result[i] = json;
        }
        return result;
    }

    /**
     * 卡号过滤 规则卡号：655598******4554（保留前六后四）
     *
     * @return
     */
    private JSONObject cardNoDesensitization(JSONObject json,
                                             List<String> cardNames) {
        if (json == null || cardNames == null)
            return json;
        Set<Map.Entry<String, Object>> set = json.entrySet();
        Iterator<Map.Entry<String, Object>> it = set.iterator();
        while (it.hasNext()) {
            Map.Entry<String, Object> entry = it.next();
            String Key = entry.getKey();
            Object value = entry.getValue();

            if (cardNames.contains(Key)) {// 如果包含敏感字段替换

                if (value != null) {
                    if (value instanceof String) {
                        String strV = (String) value;
                        json.put(
                                Key,
                                strV.substring(0, 6)
                                        + "******"
                                        + strV.substring(strV.length() - 3,
                                        strV.length()));
                    } else if (value instanceof JSONArray) {
                        JSONArray strA = (JSONArray) value;
                        if (strA.isEmpty())
                            continue;
                        JSONArray strB = new JSONArray();
                        for (int i = 0; i < strA.size(); i++) {
                            Object newObject = strA.get(i);

                            if (newObject instanceof String) {
                                String newV = (String) newObject;

                                strB.add(newV.substring(0, 7)
                                        + "** ****"
                                        + newV.substring(newV.length() - 4,
                                        newV.length()));
                            } else if (newObject instanceof JSONObject) {
                                strB.add(cardNoDesensitization(
                                        (JSONObject) newObject, cardNames));
                            } else {
                                strB.add(newObject);
                            }

                        }
                        json.put(Key, strB);
                    }else if (value instanceof JSONObject) {
                        json.put(Key,
                                cardNoDesensitization((JSONObject) value, cardNames));
                    }

                }

            } else if (value instanceof JSONObject) {

                json.put(Key,
                        cardNoDesensitization((JSONObject) value, cardNames));
            } else if (value instanceof JSONArray) {

                JSONArray cJsonArray = (JSONArray) value;
                JSONArray ccjsonArray = new JSONArray();
                for (int j = 0; j < cJsonArray.size(); j++) {
                    Object ccObject = cJsonArray.get(j);
                    if (ccObject instanceof JSONObject) {
                        ccjsonArray.add(cardNoDesensitization(
                                (JSONObject) ccObject, cardNames));
                    } else {
                        ccjsonArray.add(ccObject);
                    }
                }

                json.put(Key, ccjsonArray);
            } else if (value instanceof String) {
                try {
                    JSONObject vJson = JSONObject.parseObject(handleStringBeforeParse((String) value));
                    json.put(Key, cardNoDesensitization(vJson, cardNames));
                } catch (Exception e) {
                    // 非敏感字段 非json格式不做处理
                }

            }

        }

        return json;

    }

    /**
     * 用户姓名脱敏
     *
     * @param json
     *            姓名：李*安、王*（遮掩中间一位）英文：zha**hao（前三后三）
     */
    private JSONObject custNameDesensitization(JSONObject json,
                                               List<String> custKeyNames) {

        if (json == null || custKeyNames == null)
            return json;

        Set<Map.Entry<String, Object>> set = json.entrySet();
        Iterator<Map.Entry<String, Object>> it = set.iterator();

        while (it.hasNext()) {
            Map.Entry<String, Object> entry = it.next();
            String key = entry.getKey();
            Object OV = entry.getValue();

            if (custKeyNames.contains(key)) {
                if (OV != null) {

                    if (OV instanceof String) {
                        String value = (String) OV;
                        if (isChinese(value)) {// 中文
                            if (value.length() >= 2) {
                                json.put(
                                        key,
                                        new StringBuilder(value).replace(1, 2,
                                                "*").toString());
                            }

                        } else {// 英文

                            if (value.length() > 6) {
                                json.put(
                                        key,
                                        new StringBuilder(value).replace(3,
                                                value.length() - 3,
                                                getXinXin(value.length() - 6))
                                                .toString());
                            } else {
                                json.put(key, getXinXin(value.length()));

                            }
                        }
                    } else if (OV instanceof String[]) {// 如果是字符串数组
                        String[] values = (String[]) OV;
                        if (values.length == 0)
                            continue;
                        for (int i = 0; i < values.length; i++) {
                            if (isChinese(values[i]) && values[i].length() >= 2) {
                                values[i] = new StringBuilder(values[i])
                                        .replace(1, 2, "*").toString();
                            } else {
                                if (values[i].length() > 6) {
                                    values[i] = new StringBuilder(values[i])
                                            .replace(
                                                    3,
                                                    values[i].length() - 3,
                                                    getXinXin(values[i]
                                                            .length() - 6))
                                            .toString();
                                } else {
                                    values[i] = getXinXin(values[i].length());
                                }
                            }

                        }
                        json.put(key, values);

                    } else if (OV instanceof JSONArray) {
                        JSONArray jsonA = (JSONArray) OV;
                        if (jsonA.isEmpty())
                            continue;
                        JSONArray jsonB = new JSONArray();
                        for (int i = 0; i < jsonA.size(); i++) {

                            if (jsonA.get(i) instanceof JSONObject) {
                                jsonB.add(custNameDesensitization(
                                        (JSONObject) jsonA.get(i), custKeyNames));
                                continue;
                            } else if (!(jsonA.get(i) instanceof String)) {
                                jsonB.add(jsonA.get(i));
                                continue;
                            }
                            String newV = (String) jsonA.get(i);
                            if (isChinese(newV) && newV.length() >= 2) {
                                jsonB.add(new StringBuilder(newV).replace(1, 2,
                                        "*").toString());
                            } else {
                                if (newV.length() > 6) {
                                    jsonB.add(new StringBuilder(newV).replace(
                                            3, newV.length() - 3,
                                            getXinXin(newV.length() - 6))
                                            .toString());
                                } else {
                                    jsonB.add(getXinXin(newV.length()));
                                }
                            }
                        }

                        json.put(key, jsonB);

                    } else if (OV instanceof JSONObject) {

                        json.put(key,
                                custNameDesensitization((JSONObject) OV, custKeyNames));
                    }

                }

            } else if (OV instanceof JSONObject) {

                json.put(key,
                        custNameDesensitization((JSONObject) OV, custKeyNames));
            } else if (OV instanceof JSONArray) {

                JSONArray cJsonArray = (JSONArray) OV;
                JSONArray ccjsonArray = new JSONArray();
                for (int j = 0; j < cJsonArray.size(); j++) {
                    Object ccObject = cJsonArray.get(j);
                    if (ccObject instanceof JSONObject) {
                        ccjsonArray.add(custNameDesensitization(
                                (JSONObject) ccObject, custKeyNames));
                    } else {
                        ccjsonArray.add(ccObject);
                    }
                }

                json.put(key, ccjsonArray);
            } else if (OV instanceof String) {
                try {
                    JSONObject vJson = JSONObject.parseObject(handleStringBeforeParse((String) OV));
                    json.put(key, custNameDesensitization(vJson, custKeyNames));
                } catch (Exception e) {
                    // 非敏感字段 非json格式不做处理
                }

            }

        }
        return json;
    }

    /**
     * 手机号脱敏 手机号：137******48（前3位及后2位 130******83）
     *
     * @param json
     */
    private JSONObject mobileNoDesensitization(JSONObject json,
                                               List<String> phoneKeyNames) {
        if (json == null || phoneKeyNames == null)
            return json;

        Set<Map.Entry<String, Object>> set = json.entrySet();
        Iterator<Map.Entry<String, Object>> it = set.iterator();

        while (it.hasNext()) {
            Map.Entry<String, Object> entry = it.next();
            String key = entry.getKey();
            Object ov = entry.getValue();

            if (phoneKeyNames.contains(key)) {
                if (ov != null) {
                    if (ov instanceof String) {
                        String value = (String) ov;
                        if (value.length() >= 11)
                            json.put(key, new StringBuilder(value).replace(3,
                                    9, "******"));
                    } else if (ov instanceof String[]) {
                        String[] values = (String[]) ov;
                        if (values.length == 0)
                            continue;
                        for (int i = 0; i < values.length; i++) {
                            if (values[i].length() < 11)
                                continue;
                            values[i] = new StringBuilder(values[i]).replace(4,
                                    7, "****").toString();
                        }

                        json.put(key, values);
                    } else if (ov instanceof JSONArray) {
                        JSONArray jsonA = (JSONArray) ov;
                        if (jsonA.isEmpty())
                            continue;
                        JSONArray jsonB = new JSONArray();

                        for (int i = 0; i < jsonA.size(); i++) {
                            Object newA = jsonA.get(i);
                            if (newA instanceof JSONObject) {
                                jsonB.add(mobileNoDesensitization(
                                        (JSONObject) newA, phoneKeyNames));
                                continue;
                            } else if (!(newA instanceof String)) {
                                jsonB.add(newA);
                                continue;
                            }

                            String newV = (String) newA;
                            if (newV.length() >= 11)
                                jsonB.add(new StringBuilder(newV).replace(4, 7,
                                        "****").toString());

                        }
                        json.put(key, jsonB);
                    } else if (ov instanceof JSONObject) {

                        json.put(key,
                                mobileNoDesensitization((JSONObject) ov, phoneKeyNames));

                    }
                }

            } else if (ov instanceof JSONObject) {

                json.put(key,
                        mobileNoDesensitization((JSONObject) ov, phoneKeyNames));

            } else if (ov instanceof JSONArray) {

                JSONArray cJsonArray = (JSONArray) ov;
                JSONArray ccjsonArray = new JSONArray();
                for (int j = 0; j < cJsonArray.size(); j++) {
                    Object ccObject = cJsonArray.get(j);
                    if (ccObject instanceof JSONObject) {
                        ccjsonArray.add(mobileNoDesensitization(
                                (JSONObject) ccObject, phoneKeyNames));
                    } else {
                        ccjsonArray.add(ccObject);
                    }
                }

                json.put(key, ccjsonArray);
            } else if (ov instanceof String) {
                try {
                    JSONObject vJson = JSONObject.parseObject(handleStringBeforeParse((String) ov));
                    json.put(key, custNameDesensitization(vJson, phoneKeyNames));
                } catch (Exception e) {
                    // 非敏感字段 非json格式不做处理
                }

            }

        }

        return json;

    }

    /**
     * 邮箱脱敏 59****97@qq.com（保留前二后二）
     *
     * @param json
     */
    private JSONObject emailDesensitization(JSONObject json,
                                            List<String> emailKeyNames) {
        if (json == null || emailKeyNames == null)
            return json;

        Set<Map.Entry<String, Object>> set = json.entrySet();
        Iterator<Map.Entry<String, Object>> it = set.iterator();
        while (it.hasNext()) {
            Map.Entry<String, Object> entry = it.next();
            String key = entry.getKey();
            Object ov = entry.getValue();
            if (emailKeyNames.contains(key)) {
                if (ov != null) {
                    if (ov instanceof String) {
                        String value = (String) ov;
                        int endIndex = value.indexOf("@");
                        if (endIndex > 4)
                            json.put(
                                    key,
                                    new StringBuilder(value).replace(2,
                                            endIndex - 2,
                                            getXinXin(endIndex - 4)).toString());
                    } else if (ov instanceof String[]) {
                        String[] values = (String[]) ov;
                        if (values.length == 0)
                            continue;
                        for (int i = 0; i < values.length; i++) {
                            int endIndex = values[i].indexOf("@");
                            if (endIndex > 4)
                                values[i] = new StringBuilder(values[i])
                                        .replace(2, endIndex - 2,
                                                getXinXin(endIndex - 4))
                                        .toString();
                        }

                        json.put(key, values);
                    } else if (ov instanceof JSONArray) {
                        JSONArray jsonA = (JSONArray) ov;
                        if (jsonA.isEmpty())
                            continue;
                        JSONArray jsonB = new JSONArray();
                        for (int i = 0; i < jsonA.size(); i++) {
                            Object oa = jsonA.get(i);
                            if (oa instanceof JSONObject) {
                                jsonB.add(emailDesensitization((JSONObject) oa,
                                        emailKeyNames));
                                continue;
                            } else if (!(oa instanceof String)) {
                                jsonB.add(oa);
                                continue;
                            }

                            String newV = (String) oa;
                            int endIndex = newV.indexOf("@");
                            if (endIndex > 4)
                                jsonB.add(new StringBuilder(newV).replace(2,
                                        endIndex - 2, getXinXin(endIndex - 4))
                                        .toString());
                        }

                        json.put(key, jsonB);

                    } else if (ov instanceof JSONObject) {

                        json.put(key,
                                emailDesensitization((JSONObject) ov, emailKeyNames));
                    }
                }
            } else if (ov instanceof JSONObject) {

                json.put(key,
                        emailDesensitization((JSONObject) ov, emailKeyNames));
            } else if (ov instanceof JSONArray) {

                JSONArray cJsonArray = (JSONArray) ov;
                JSONArray ccjsonArray = new JSONArray();
                for (int j = 0; j < cJsonArray.size(); j++) {
                    Object ccObject = cJsonArray.get(j);
                    if (ccObject instanceof JSONObject) {
                        ccjsonArray.add(emailDesensitization(
                                (JSONObject) ccObject, emailKeyNames));
                    } else {
                        ccjsonArray.add(ccObject);
                    }
                }

                json.put(key, ccjsonArray);
            } else if (ov instanceof String) {
                try {
                    JSONObject vJson = JSONObject.parseObject(handleStringBeforeParse((String) ov));
                    json.put(key, emailDesensitization(vJson, emailKeyNames));
                } catch (Exception e) {
                    // 非敏感字段 非json格式不做处理
                }

            }

        }

        return json;
    }

    /**
     * 省份证信息脱敏 身份证： 440301 ******** 5219（遮掩年月日部分
     *
     * @param json
     */
    private JSONObject idNoDesensitization(JSONObject json,
                                           List<String> idNoKeyNames) {
        if (json == null || idNoKeyNames == null)
            return json;

        Set<Map.Entry<String, Object>> set = json.entrySet();
        Iterator<Map.Entry<String, Object>> it = set.iterator();

        while (it.hasNext()) {
            Map.Entry<String, Object> entry = it.next();
            String key = entry.getKey();
            Object ov = entry.getValue();
            if (idNoKeyNames.contains(key)) {
                if (ov != null) {
                    if (ov instanceof String) {
                        String value = (String) ov;
                        if (value.length() < 10)
                            continue;
                        json.put(
                                key,
                                new StringBuilder(value).replace(6,
                                        value.length() - 4, "********"));
                    } else if (ov instanceof String[]) {
                        String[] values = (String[]) ov;
                        if (values.length == 0)
                            continue;
                        for (int i = 0; i < values.length; i++) {
                            if (values[i].length() < 10)
                                continue;
                            values[i] = new StringBuilder(values[i]).replace(6,
                                    values[i].length() - 4, "********")
                                    .toString();

                        }
                        json.put(key, values);
                    } else if (ov instanceof JSONArray) {
                        JSONArray jsonA = (JSONArray) ov;
                        if (jsonA.isEmpty())
                            continue;

                        JSONArray jsonB = new JSONArray();
                        for (int i = 0; i < jsonA.size(); i++) {

                            if (jsonA.get(i) instanceof String) {
                                String newV = (String) jsonA.get(i);
                                if (newV.length() >= 10) {
                                    jsonB.add(new StringBuilder(newV).replace(
                                            6, newV.length() - 4, "********")
                                            .toString());
                                    continue;
                                }
                                jsonB.add(newV);
                            } else if (jsonA.get(i) instanceof JSONObject) {
                                jsonB.add(this.idNoDesensitization(
                                        (JSONObject) jsonA.get(i), idNoKeyNames));

                            } else {
                                jsonB.add(jsonA.get(i));
                            }
                        }

                        json.put(key, jsonB);

                    } else if (ov instanceof JSONObject) {

                        json.put(key,
                                this.idNoDesensitization((JSONObject) ov, idNoKeyNames));
                    }

                }
            } else if (ov instanceof JSONObject) {

                json.put(key,
                        this.idNoDesensitization((JSONObject) ov, idNoKeyNames));
            } else if (ov instanceof JSONArray) {

                JSONArray cJsonArray = (JSONArray) ov;
                JSONArray ccjsonArray = new JSONArray();
                for (int j = 0; j < cJsonArray.size(); j++) {
                    Object ccObject = cJsonArray.get(j);
                    if (ccObject instanceof JSONObject) {
                        ccjsonArray.add(idNoDesensitization(
                                (JSONObject) ccObject, idNoKeyNames));
                    } else {
                        ccjsonArray.add(ccObject);
                    }
                }

                json.put(key, ccjsonArray);
            } else if (ov instanceof String) {
                try {
                    JSONObject vJson = JSONObject.parseObject(handleStringBeforeParse((String) ov));
                    json.put(key, idNoDesensitization(vJson, idNoKeyNames));
                } catch (Exception e) {
                    // 非敏感字段 非json格式不做处理
                }

            }

        }

        return json;
    }

    /**
     * 家庭住址 前三 后三
     *
     * @param json
     */
    private JSONObject hemoAddressDesensitization(JSONObject json,
                                                  List<String> homeAddressKeys) {
        // String[] homeAddressKeys=map.get("homeAddressKeys");
        if (json == null || homeAddressKeys == null)
            return json;

        Set<Map.Entry<String, Object>> set = json.entrySet();
        Iterator<Map.Entry<String, Object>> it = set.iterator();

        while (it.hasNext()) {
            Map.Entry<String, Object> entry = it.next();
            String key = entry.getKey();
            Object ov = entry.getValue();
            if (homeAddressKeys.contains(key)) {

                if (ov != null) {
                    if (ov instanceof String) {
                        String value = (String) ov;
                        if (value.length() > 6) {
                            json.put(
                                    key,
                                    new StringBuilder(value).replace(3,
                                            value.length() - 3,
                                            getXinXin(value.length() - 6)));
                        }
                    } else if (ov instanceof String[]) {
                        String[] values = (String[]) ov;
                        if (values.length == 0)
                            continue;
                        for (int i = 0; i < values.length; i++) {
                            if (values[i] == null || values[i].length() < 6)
                                continue;
                            values[i] = new StringBuilder(values[i]).replace(3,
                                    values[i].length() - 3,
                                    getXinXin(values[i].length() - 6))
                                    .toString();
                        }
                        json.put(key, values);
                    } else if (ov instanceof JSONArray) {
                        JSONArray jsonA = (JSONArray) ov;
                        if (jsonA.isEmpty())
                            continue;
                        JSONArray jsonB = new JSONArray();
                        for (int i = 0; i < jsonA.size(); i++) {
                            if (jsonA.get(i) instanceof JSONObject) {
                                jsonB.add(this.hemoAddressDesensitization(
                                        (JSONObject) jsonA.get(i),
                                        homeAddressKeys));
                                continue;
                            } else if (!(jsonA.get(i) instanceof String)) {
                                jsonB.add(jsonA.get(i));
                                continue;
                            }
                            String newV = (String) jsonA.get(i);
                            if (newV.length() < 6) {
                                jsonB.add(newV);
                                continue;
                            }
                            jsonB.add(new StringBuilder(newV).replace(3,
                                    newV.length() - 3,
                                    getXinXin(newV.length() - 6)).toString());

                        }

                        json.put(key, jsonB);

                    } else if (ov instanceof JSONObject) {

                        json.put(key, this.hemoAddressDesensitization((JSONObject) ov,
                                homeAddressKeys));

                    }

                }
            } else if (ov instanceof JSONObject) {

                json.put(key, this.hemoAddressDesensitization((JSONObject) ov,
                        homeAddressKeys));

            } else if (ov instanceof JSONArray) {

                JSONArray cJsonArray = (JSONArray) ov;
                JSONArray ccjsonArray = new JSONArray();
                for (int j = 0; j < cJsonArray.size(); j++) {
                    Object ccObject = cJsonArray.get(j);
                    if (ccObject instanceof JSONObject) {
                        ccjsonArray.add(hemoAddressDesensitization(
                                (JSONObject) ccObject, homeAddressKeys));
                    } else {
                        ccjsonArray.add(ccObject);
                    }
                }

                json.put(key, ccjsonArray);
            } else if (ov instanceof String) {
                try {
                    JSONObject vJson = JSONObject.parseObject(handleStringBeforeParse((String) ov));
                    json.put(key,
                            hemoAddressDesensitization(vJson, homeAddressKeys));
                } catch (Exception e) {
                    // 非敏感字段 非json格式不做处理
                }

            }

        }

        return json;

    }

    /**
     * 其它
     *
     * @param json
     */
    private JSONObject otherDesensitization(JSONObject json,
                                            List<String> otherKeyNames) {

        if (json == null || otherKeyNames == null)
            return json;

        Set<Map.Entry<String, Object>> set = json.entrySet();
        Iterator<Map.Entry<String, Object>> it = set.iterator();

        while (it.hasNext()) {
            Map.Entry<String, Object> entry = it.next();
            String key = entry.getKey();
            Object value = entry.getValue();
            if (otherKeyNames.contains(key)) {
                String mvalue = JSONObject.toJSONString(value);
                if (mvalue != null && !"".equals(mvalue)) {
                    json.put(key, getXinXin(mvalue.length()));
                }

            } else if (value instanceof JSONObject) {
                json.put(key,
                        otherDesensitization((JSONObject) value, otherKeyNames));
            } else if (value instanceof JSONArray) {

                JSONArray cJsonArray = (JSONArray) value;
                JSONArray ccjsonArray = new JSONArray();
                for (int j = 0; j < cJsonArray.size(); j++) {
                    Object ccObject = cJsonArray.get(j);
                    if (ccObject instanceof JSONObject) {
                        ccjsonArray.add(otherDesensitization(
                                (JSONObject) ccObject, otherKeyNames));
                    } else {
                        ccjsonArray.add(ccObject);
                    }
                }

                json.put(key, ccjsonArray);
            } else if (value instanceof String) {
                try {
                    JSONObject vJson = JSONObject.parseObject(handleStringBeforeParse((String) value));
                    json.put(key, otherDesensitization(vJson, otherKeyNames));
                } catch (Exception e) {
                    // 非敏感字段 非json格式不做处理
                }

            }
        }

        return json;
    }

    private static String getXinXin(int length) {
        StringBuffer strB = new StringBuffer();
        for (int i = 0; i < length; i++) {
            strB.append("*");
        }
        return strB.toString();
    }

    private boolean isChinese(String str) {
        String regexStr = "[\u4E00-\u9FA5]";
        Pattern p = Pattern.compile(regexStr);
        Matcher m = p.matcher(str);
        return m.find();
    }

    private static String handleStringBeforeParse(String input) {
        if (StringUtils.isBlank(input)) {
            return "";
        }

        String pattern1 = "\\{\"\\$ref\":\"[@\\$]\"\\}";
        String pattern2 = "\\{\"\\$ref\":\"(\\.){2}\"\\}";
        String pattern3 = "\\{\"\\$ref\":\"(\\$\\.children\\.\\d+)\"\\}";
        return input.replaceAll(pattern1, "null")
                .replaceAll(pattern2, "null")
                .replaceAll(pattern3, "null");
    }

    public static void main(String[] args) {

        // 生成特定的json字符串
        generateJsonString("bankCardNo,bindCardNo,bindAccount,bindAccountNo,custAccount,pamaAcct,customerId,clientNo,accountsNo,electronicAccount");
        generateJsonString("name,cifName,cnName,cstName,customerName,userName,cifName,pay_user_name,updatedBy,createdBy,custName,customerNameCN,accountName,payeeName,payAccName,recAccName");
        generateJsonString("phoneNum,mobileNo,userId,mobile,newMobileNo,account_login,loginAlias,referrer,cardMobileNo,phone,requestMobileNo,registerMobileNo,telePhone,bindCardMobile,requestOTP,fuserName,reference,fmobile,phoneNumber,information,recAcc,changeMoblieNo,oldMobileNo");
        generateJsonString("email");
        generateJsonString("idnumber,credNo,IdNo,idNo,certNo,user_id_no,card_number,idNumber,idNumber,cardNo,fidNo,saveCardNo,payAcct,payAcc,receiveAcct,eaccountNo,accountNo,payeeAcct,payerAcct,payerAccount,realPayerAccount,returnField,uesr,idNoCheck");
        generateJsonString("homeAddress,address");
        generateJsonString("text,password,SMScode,smsCode,fileName,orderExtInfo,birthDate,user,plateNum,content");


    }

    static void generateJsonString(String fieldsStr) {
        String[] fields = fieldsStr.split(",");

        JSONObject jsonObject = new JSONObject();
        for (String field: fields ) {
            jsonObject.put(field, "112233445566778899");
        }

        System.out.println(jsonObject.toJSONString());
    }
}
